package com.gs.common.websocket.server;

import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.gs.common.constant.Constant;
import com.gs.common.websocket.config.WebSocketConfig;
import com.gs.common.websocket.entity.WebSocketData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.security.Principal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @title: 孙杨申
 * @date 2021/12/11 20:40
 * javax.websocket版本
 */

@Component
@Slf4j
@ServerEndpoint(value = "/test", configurator = WebSocketConfig.class)
public class WebSocketServer {

    public static final Map<String, WebSocketData> serverClients = new ConcurrentHashMap<>();

    /**
     * To execute when it connected
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        log.info("opOpen:" + session.getId());
        WebSocketData data = new WebSocketData();
        data.setUserId((Long) session.getUserProperties().get(Constant.USER_KEY));
        data.setSession(session);
        serverClients.put(session.getId(), data);
    }

    /**
     * To execute when get message
     * @param message
     * @param session
     * @return
     */
    @OnMessage
    public void onMessage(String message, Session session) {

        log.info("onMessage: " + message + ",sessionId:" + session.getId());
        WebSocketData data = new WebSocketData();
        data.setMsg("pong");
        sendMessage(session, data);
    }

    /**
     * To execute when closed the connector
     * @param session
     * @param closeReason
     */
    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        log.info("onClose:" + session.getId());
    }

    /**
     * To execute when an error occurs
     * @param t
     */
    @OnError
    public void onError(Throwable t) {
        log.info("onError", t);
    }


    /**
     * 发送信息
     *
     * @param userIdList 用户ID列表
     * @param message    消息内容
     */
    public void sendMessage(List<Long> userIdList, WebSocketData message) {
        log.debug("sendMessage userIdList ：" + message.toString());
        userIdList.forEach(userId -> sendMessage(userId, message));
    }

    /**
     * 发送信息
     *
     * @param userId  用户ID
     * @param message 消息内容
     */
    public void sendMessage(Long userId, WebSocketData message) {
        serverClients.values().forEach(info -> {
            if (userId.equals(info.getUserId())) {
                sendMessage(info.getSession(), message);
            }
        });
    }

    /**
     * 发送信息给全部用户
     *
     * @param message 消息内容
     */
    public void sendMessageAll(WebSocketData message) {
        serverClients.values().forEach(info -> sendMessage(info.getSession(), message));
    }

    public void sendMessage(Session session, WebSocketData message) {
        try {
            session.getBasicRemote().sendText(JSON.toJSONString(message));
        } catch (IOException e) {
            log.error("send message error，" + e.getMessage(), e);
        }
    }


    /**
     * 获取所有当前连接的用户Session
     *
     * @return 所有连接的session集合
     */
    public List<Session> getAllUserSession() {

        Set<String> keySet = serverClients.keySet();

        String[] tempStr = new String[keySet.size()];

        String[] finalStr = keySet.toArray(tempStr);

        List<Session> sessions = new ArrayList<>();

        for (String index : finalStr) {

            Session session = serverClients.get(index).getSession();

            sessions.add(session);
        }

        return sessions;

    }
    /**
     * 获取所有当前连接的用户Session
     *
     * @return 所有连接的session集合
     */
    public static List getUserMap() {

        Set<String> keySet =  serverClients.keySet();

        String[] tempStr = new String[keySet.size()];

        String[] finalStr = keySet.toArray(tempStr);

        List<Map<String, Object>> list = new ArrayList<>();

        for (String index : finalStr) {
            WebSocketData webSocketData = serverClients.get(index);
            Session session = webSocketData.getSession();
            Map<String, Object> map = new HashMap<>();
            Principal userPrincipal = session.getUserPrincipal();
            JSONObject jsonObject = new JSONObject(userPrincipal);
            JSONObject object = jsonObject.getJSONObject("object");
            Long id = object.getLong("id");
            String username = object.getStr("username");
            map.put("id", id);
            map.put("sessionId", session.getId());
            map.put("username", username);
//            map.put("createTime", DateUtils.format(webSocketData.getCreateTime(), DateUtils.DATE_TIME_PATTERN));

            map.put("queryString", session.getQueryString());
            list.add(map);
        }

        return list;

    }
}
